package com.haotian.web;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.haotian.web.exception._FileUploadNoMultipartException;
import com.haotian.web.fileupload._FileUploadConfig;
import com.haotian.web.fileupload._FileUploadResult;

public final class _RequestUtils {

	private _RequestUtils() {
	}

	/**
	 * 以 Map 形式 返回请求的参数
	 * 
	 * @param req
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static final Map<String, String> getParam2Map(HttpServletRequest req) throws Exception {
		Map<String, String> params = new HashMap<>();
		Enumeration<String> parameterNames = req.getParameterNames();
		while (parameterNames.hasMoreElements()) {
			String name = parameterNames.nextElement();
			String value = req.getParameter(name);
			params.put(name, value);
		}
		return params;
	}

	/**
	 * 获取用户IP地址
	 * 
	 * @param req
	 * @return
	 */
	public static final String getRemoteAddr(HttpServletRequest req) {
		if (req.getHeader("x-forwarded-for") == null) {
			return req.getRemoteAddr();
		} else {
			return req.getHeader("x-forwarded-for");
		}
	}

	/**
	 * 获取请求的路径<br>
	 * 
	 * 例如请求：http://localhost/TestPDFText/id
	 * 
	 * 结果为：/TestPDFText/id
	 * 
	 * @param req
	 * @return
	 */
	public final static String getRequestURI(HttpServletRequest req) {
		return req.getRequestURI();
	}

	/**
	 * 获取请求的完整路径<br>
	 * 
	 * 例如请求：http://localhost/TestPDFText/id
	 * 
	 * 结果为：http://localhost/TestPDFText/id
	 * 
	 * @param req
	 * @return
	 */
	public final static String getRequestURL(HttpServletRequest req) {
		return req.getRequestURL().toString();
	}

	/**
	 * 验证请求参数是否为空字符或null
	 * 
	 * @param param
	 *            要验证的参数 数组
	 * 
	 * @return 如果存在" "或null 返回true
	 */
	public static boolean ParamIsBlank(String... param) {

		for (int i = 0; i < param.length; i++) {
			if (StringUtils.isBlank(param[i])) {
				return true;
			}

		}
		return false;

	}

	/**
	 * 获取请求数据流为com.alibaba.fastjson.JSONObject
	 * 
	 * @param req
	 * @return
	 * @throws IOException
	 */
	public static JSONObject getBody2JSON(HttpServletRequest req, String charset) throws IOException {
		try (
				// 输入流
				ServletInputStream inputStream = req.getInputStream();
				// 缓冲器
				ByteArrayOutputStream baos = new ByteArrayOutputStream();

		) {

			// 临时缓存
			byte[] buff = new byte[512];

			// 读取字节数
			int readLen = -1;
			// 开始读取
			while ((readLen = inputStream.read(buff)) != -1) {
				// 存入缓冲器
				baos.write(buff, 0, readLen);
			}

			byte[] byteArray = baos.toByteArray();

			return JSON.parseObject(new String(byteArray, charset));
		}

	}

	/**
	 * 获取表单请求中文件上传参数 请求类型为 multipart/form-data POST
	 * 
	 * 可使用{@link com.haotian.http._HttpKit} 中的 postMultipartFormData 函数做请求配合使用
	 * 
	 * 也可使用页面表单 或自行开发
	 * 
	 * @param config
	 *            上传配置类 _FileUploadConfig
	 * @return
	 * @throws Exception
	 */
	public static _FileUploadResult getFileUploadResult(_FileUploadConfig config) throws Exception {

		_FileUploadResult result = new _FileUploadResult();

		// 检测是否为多媒体上传
		if (!ServletFileUpload.isMultipartContent(config.getRequest())) {
			// 如果不是则停止
			throw new _FileUploadNoMultipartException("表单必须包含 enctype=multipart/form-data");
		}

		// 配置上传参数
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
		factory.setSizeThreshold(config.getMEMORY_THRESHOLD());

		// 设置临时存储目录
		factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

		ServletFileUpload upload = new ServletFileUpload(factory);

		// 设置最大文件上传值
		upload.setFileSizeMax(config.getMAX_FILE_SIZE());

		// 设置最大请求值 (包含文件和表单数据)
		upload.setSizeMax(config.getMAX_REQUEST_SIZE());

		// 设置编码
		upload.setHeaderEncoding(config.getEncoding());

		// 解析请求的内容提取文件数据
		List<FileItem> formItems = upload.parseRequest(config.getRequest());

		if (config.getUPLOAD_DIRECTORY() != null) {

			File uploadDir = new File(config.getUPLOAD_DIRECTORY());

			// 如果目录不存在则创建
			if (!uploadDir.exists()) {
				uploadDir.mkdirs();
			}
		}

		if (formItems != null && formItems.size() > 0) {
			// 迭代表单数据
			for (FileItem item : formItems) {

				// 跳过空表单
				if (item.getSize() <= 0) {
					continue;
				}

				// 文件上传域
				if (!item.isFormField()) {

					File file = new File(item.getName());

					if (config.getUPLOAD_DIRECTORY() != null) {
						String filePath = config.getUPLOAD_DIRECTORY() + File.separator + file.getName();
						File storeFile = new File(filePath);
						// 保存文件到硬盘
						item.write(storeFile);
					} else {
						String tempPath = System.getProperty("java.io.tmpdir") + File.separator + file.getName();
						File tempFile = new File(tempPath);
						// 保存文件到硬盘
						item.write(tempFile);
						// 没有设置上传路径则加入到返回的文件集合由调用者自行处理 否则集合的size为0
						result.getFiles().add(tempFile);
					}
				} else {// 普通表单域
					String key = item.getFieldName();
					String value = item.getString(config.getEncoding());
					result.setParam(key, value);
				}
			}
		}

		return result;
	}

}
